package com.demo.core.service.impl;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Blob;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import com.demo.common.ImageUtils;
import com.demo.core.dao.FileDao;
import com.demo.core.dao.FolderDao;
import com.demo.core.model.File;
import com.demo.core.model.Folder;
import com.demo.core.model.support.converter.AdjacencyListToChainedObjectConverter;
import com.demo.core.service.DocumentService;

/**
 * 文档服务实现
 * 实现文档目录和文档的管理
 * 
 * @author ryuu.kk
 */
public class DocumentServiceImpl implements DocumentService {

	/**
	 * 文件夹数据访问层
	 */
	private FolderDao folderDao;
	/**
	 * 文件数据访问层
	 */
	private FileDao fileDao;
	
	@Override
	public Long createFolder(Folder folder) {
		return folderDao.insert(folder);
	}

	@Override
	@Transactional
	public void deleteFolder(Long folderId) {
		Map<String, Object> params = new HashMap<String, Object>(2);
		params.put("folderId", folderId);
		fileDao.delete(params);
		folderDao.delete(folderId);
	}

	@Override
	public Long createFile(File file) {
		return fileDao.insert(file);
	}

	@Override
	public void deleteFild(Long fileId) {
		fileDao.delete(fileId);
	}

	@Override
	public void deleteFild(String uuid) {
		Map<String, Object> params = new HashMap<String, Object>(3);
		params.put("uuid", uuid);
		fileDao.delete(params);
	}
	
	@Override
	public List<Folder> ownFolder(Long ownerSid) {
		Map<String, Object> params = new HashMap<String, Object>(3);
		params.put("ownerSid", ownerSid);
		return folderDao.select(params);
	}

	@Override
	public Folder findFolder(Long folderId) {
		return folderDao.select(folderId);
	}

	@Override
	public Folder findFolder(String uuid) {
		return folderDao.find(uuid);
	}
	
	@Override
	public List<Folder> findFolder(Long siteId, Long pid) {
		Map<String, Object> params = new HashMap<String, Object>(4);
		params.put("siteId", siteId);
		params.put("pid", pid);
		return folderDao.select(params);
	}

	@Override
	public Folder tree(Long folderId) {
		Map<String, Object> params = new HashMap<String, Object>(2);
		params.put("id", folderId);
		List<Folder> folderList = folderDao.tree(params);
		return AdjacencyListToChainedObjectConverter.conver(folderList);
	}

	@Override
	public Folder tree(Long folderId, int depth) {
		Map<String, Object> params = new HashMap<String, Object>(2);
		List<Integer> depths = new ArrayList<Integer>(1);
		depths.add(depth);
		params.put("id", folderId);
		params.put("depthList", depths);
		List<Folder> folderList = folderDao.tree(params);
		return AdjacencyListToChainedObjectConverter.conver(folderList);
	}

	@Override
	public Folder tree(Long folderId, List<Integer> depthList) {
		Map<String, Object> params = new HashMap<String, Object>(2);
		params.put("id", folderId);
		params.put("depthList", depthList);
		List<Folder> folderList = folderDao.tree(params);
		return AdjacencyListToChainedObjectConverter.conver(folderList);
	}

	@Override
	public File findFile(Long fileId) {
		return findFile(fileId, false);
	}

	@Override
	public File findFile(Long fileId, boolean isContent) {
		Map<String, Object> params = new HashMap<String, Object>(4);
		params.put("id", fileId);
		params.put("isContent", isContent);
		List<File> fileList = fileDao.select(params);
		return fileList.size() == 0 ? null : fileList.get(0);
	}
	
	@Override
	public File findFile(String uuid) {
		return findFile(uuid, false);
	}

	@Override
	public File findFile(String uuid, Boolean isContent) {
		Map<String, Object> params = new HashMap<String, Object>(4);
		params.put("uuid", uuid);
		params.put("isContent", isContent);
		List<File> fileList = fileDao.select(params);
		return fileList.size() > 0 ? fileList.get(0) : null;
	}
	
	@Override
	public List<File> findFileList(Long folderId) {
		return findFileList(folderId, false);
	}

	@Override
	public List<File> findFileList(Long folderId, boolean isContent) {
		Map<String, Object> params = new HashMap<String, Object>(4);
		params.put("folderId", folderId);
		params.put("isContent", isContent);
		return fileDao.select(params);
	}

	@Override
	public void validFile(Long fileId, boolean enabled, String status) {
		Map<String, Object> params = new HashMap<String, Object>(4);
		params.put("id", fileId);
		File file = new File();
		file.setEnabled(enabled);
		file.setStatus(status);
		fileDao.updateStatus(file, params);
	}

	@Override
	public void validFolder(Long folderId, boolean enabled, String status) {
		Map<String, Object> params = new HashMap<String, Object>(4);
		params.put("id", folderId);
		Folder folder = new Folder();
		folder.setEnabled(enabled);
		folder.setStatus(status);
		folderDao.update(folder, params);
	}

	@Override
	public void changeFolder(Long folderId, String name, String title, String type) {
		Map<String, Object> params = new HashMap<String, Object>(4);
		params.put("id", folderId);
		Folder folder = new Folder();
		folder.setName(name);
		folder.setType(type); 
		//title为空则使用name
		if (StringUtils.hasText(title)) {
			folder.setTitle(title);
		} else {
			folder.setTitle(name);
		}
		folderDao.update(folder, params);
	}

	@Override
	public void changeFile(Long fileId, String name, String status) {
		Map<String, Object> params = new HashMap<String, Object>(4);
		params.put("id", fileId);
		File file = new File();
		file.setName(name);
		file.setStatus(status);
		fileDao.updateStatus(file, params);
	}
	
	@Override
	public void updateFile(Long fileId, String name, byte[] content) {
		Map<String, Object> params = new HashMap<String, Object>(4);
		params.put("id", fileId);
		File file = new File();
		file.setName(name);
		file.setContent(content);
		fileDao.update(file, params);
	}

	public void setFolderDao(FolderDao folderDao) {
		this.folderDao = folderDao;
	}

	public void setFileDao(FileDao fileDao) {
		this.fileDao = fileDao;
	}

	@Override
	public byte[] queryBitFile(Long fileId) {
		return fileDao.getContent(fileId);
	}

	@Override
	public Blob queryBlobFile(Long fileId) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public InputStream queryFileStream(Long fileId) {
		return fileDao.getFileInputStream(fileId);
	}

	@Override
	public boolean fileExists(Long fileId) {
		return fileDao.exists(fileId);
	}

	@Override
	public boolean fileExists(String uuid) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("uuid", uuid);
		return fileDao.select(params).size() > 0;
	}
	
	@Override
	public boolean folderExists(Long folderId) {
		return folderDao.exists(folderId);
	}

	@Override
	public boolean folderExists(String uuid) {
		return folderDao.exists(uuid);
	}

	@Override
	public File buildImage(Long siteId, Long folderId, String uuid, String path, InputStream in) {
		
		Assert.notNull(in);
		
		// 文件名
		String name = path.substring(path.lastIndexOf("/") + 1);
		String contentType = name.substring(name.indexOf(".") + 1);
		// Long siteId = MultisiteContextHolder.getSite().getId();
		File file = new File();
		file.setFolderId(folderId);
		file.setUuid(uuid);
		file.setEnabled(true);
		file.setPath(path.substring(0, path.lastIndexOf("/") + 1));
		file.setName(name);
		file.setSiteId(siteId);
		
		file.setType(File.TYPE_INNER);
		
		// 根据路径读取文件流
		// InputStream in = context.getResourceAsStream(path);
		ByteArrayOutputStream out = null;
		BufferedImage imageInput = null;
		
		try {
			out = new ByteArrayOutputStream();
			// in = context.getResourceAsStream(path);
			imageInput = ImageUtils.buildImage(in);
			//imageInput = ImageUtils.imageZoom(ImageUtils.buildImage(in), width, height);
			
			if (imageInput != null) {
				file.setWidth(imageInput.getWidth());
				file.setHeight(imageInput.getHeight());
			}
			file.setContentType(contentType);
			ImageIO.write(imageInput, contentType, out);
			file.setContent(out.toByteArray());
			file.setSize((long)out.size());
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					// ignore
				}
			}
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {
					// ignore
				}
			}
		}
		return file;
	}

	@Override
	public File buildImage(Long siteId, Long folderId, String uuid, String path, String name, int width, int height, InputStream in) {
		// 缩略图文件名
		// String name = Constants.IMAGE_THUMB_PREFIX + path.substring(path.lastIndexOf("/") + 1);
		// 文件类型
		String contentType = name.substring(name.indexOf(".") + 1);
		//String path = path;
		// Long siteId = MultisiteContextHolder.getSite().getId();
		File file = new File();
		file.setFolderId(folderId);
		file.setUuid(uuid);
		file.setEnabled(true);
		file.setPath(path.substring(0, path.lastIndexOf("/") + 1));
		file.setName(name);
		file.setSiteId(siteId);
		
		file.setType(File.TYPE_INNER);
		
		// 根据路径读取文件流
		// InputStream in = context.getResourceAsStream(path);
		ByteArrayOutputStream out = null;
		BufferedImage imageInput = null;
		
		try {
			out = new ByteArrayOutputStream();
			// in = context.getResourceAsStream(path);
			imageInput = ImageUtils.imageZoom(ImageUtils.buildImage(in), width, height);
			
			if (imageInput != null) {
				file.setWidth(imageInput.getWidth());
				file.setHeight(imageInput.getHeight());
			}
			// 文件类型
			file.setContentType(contentType);
			// 文件写入流
			ImageIO.write(imageInput, contentType, out);
			// 设置文件bit字节
			file.setContent(out.toByteArray());
			// 设置大小
			file.setSize((long)out.size());
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					// ignore
				}
			}
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {
					// ignore
				}
			}
		}
		return file;
	}
}
